from copy import deepcopy
from typing import Any, Dict, List, Optional


def truncate_phase_tree(node: Optional[Dict[str, Any]], depth: int) -> Optional[Dict[str, Any]]:
    """
    返回限定深度的新阶段树，深度不足时标记 has_more 方便展示。
    """
    if not node or depth <= 0:
        return None

    def clone(current: Dict[str, Any], remaining: int) -> Dict[str, Any]:
        new_node: Dict[str, Any] = {
            "name": current.get("name"),
            "cost": current.get("cost"),
        }
        subs = current.get("subs") or []
        children: List[Dict[str, Any]] = []
        if remaining > 1:
            for child in subs:
                cloned = clone(child, remaining - 1)
                if cloned:
                    children.append(cloned)
        new_node["subs"] = children
        if subs and remaining <= 1:
            new_node["has_more"] = True
        return new_node

    return clone(deepcopy(node), depth)


def flatten_phase_tree(
    node: Optional[Dict[str, Any]],
    include_root: bool = True,
) -> List[Dict[str, Any]]:
    """
    扁平化阶段树，生成包含层级、路径等信息的列表。
    """
    rows: List[Dict[str, Any]] = []
    if not node:
        return rows

    def walk(current: Dict[str, Any], level: int, path: List[int]) -> None:
        cost = current.get("cost")
        rows.append(
            {
                "level": level,
                "path": ".".join(str(p) for p in path),
                "name": current.get("name", ""),
                "cost": cost,
                "has_more": current.get("has_more", False),
            }
        )
        for index, child in enumerate(current.get("subs") or [], start=1):
            walk(child, level + 1, path + [index])

    if include_root:
        walk(node, 1, [1])
    else:
        for index, child in enumerate(node.get("subs") or [], start=1):
            walk(child, 1, [index])
    return rows
